package com.miku.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.miku.blog.domain.*;
import com.miku.blog.domain.dto.*;
import com.miku.blog.domain.param.ReceptionParam;
import com.miku.blog.domain.pojo.LoginUser;
import com.miku.blog.domain.pojo.ResponseResult;
import com.miku.blog.domain.pojo.SystemConstance;
import com.miku.blog.domain.vo.*;
import com.miku.blog.eume.HttpStatusEnum;
import com.miku.blog.exception.SystemException;
import com.miku.blog.mapper.TagMapper;
import com.miku.blog.service.*;
import com.miku.blog.mapper.ArticleMapper;
import com.miku.blog.utils.BeanCopyUtils;
import com.miku.blog.utils.DateUtils;
import com.miku.blog.utils.RedisCache;
import com.miku.blog.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author Miku
 * @description 针对表【tb_article】的数据库操作Service实现
 * @createDate 2022-05-26 17:52:39
 */
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article>
        implements ArticleService {

    @Autowired
    private TagService tagService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private CommentService commentService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private LikeCountService likeCountService;
    @Autowired
    private ArticleViewService articleViewService;


    @Transactional
    @Override
    public ResponseResult saveArticle(ArticleEditVo articleEditVo) {

        Integer status = articleEditVo.getStatus();
        Integer type = articleEditVo.getType();
        Integer isTop = articleEditVo.getIsTop();
        if ((!SystemConstance.STATUS_PUBLIC.equals(status) && !SystemConstance.STATUS_PRIVATE.equals(status) && !SystemConstance.ARTICLE_STATUS_DRAFT.equals(status))
                || (!SystemConstance.ARTICLE_TYPE_BY_ORIGINAL.equals(type) && !SystemConstance.ARTICLE_TYPE_BY_REPRODUCED.equals(type) && !SystemConstance.ARTICLE_TYPE_BY_TRANSLATION.equals(type))
                || (!SystemConstance.IS_TOP.equals(isTop) && !SystemConstance.NOT_TOP.equals(isTop))
                || !StringUtils.hasText(articleEditVo.getArticleTitle())
                || !StringUtils.hasText(articleEditVo.getArticleContent())
                || (!StringUtils.hasText(articleEditVo.getOriginalUrl()) && !SystemConstance.ARTICLE_TYPE_BY_ORIGINAL.equals(type))
        ) {
            return new ResponseResult(HttpStatusEnum.PARAM_ERROR);
        }

        Article article = BeanCopyUtils.copyObjectByType(articleEditVo, Article.class);
        String categoryName = article.getCategoryName();
        Integer articleId = article.getId();
        if (articleId != null) {
            if (StringUtils.hasText(categoryName)) {
                Category category = categoryService.getCategoryByName(categoryName);
                if (Objects.isNull(category)) {
                    category = new Category().setCategoryName(categoryName);
                    categoryService.addCategories(category);
                }
                article.setCategoryId(category.getId());
            } else if (!SystemConstance.ARTICLE_STATUS_DRAFT.equals(status)) {
                return new ResponseResult(HttpStatusEnum.PARAM_ERROR);
            }

            List<String> tagNameList = articleEditVo.getTagNameList();
            if (Objects.nonNull(tagNameList) && tagNameList.size() > 0) {
                TagMapper tagMapper = (TagMapper) tagService.getBaseMapper();
                List<Tag> tagList = tagMapper.getTagListByArticleId(articleId);
                List<String> var1 = tagList.stream()
                        .map(Tag::getTagName)
                        .collect(Collectors.toList());
                if (tagNameList.size() != var1.size() || !tagNameList.containsAll(var1)) {
                    baseMapper.deleteByArticleTagTable(articleId);
                    List<Tag> tags = tagNameList.stream()
                            .map(tagName -> {
                                Tag tag = tagService.getTagByName(tagName);
                                if (Objects.isNull(tag)) {
                                    tag = new Tag().setTagName(tagName);
                                    tagService.addTags(tag);
                                }
                                return tag;
                            })
                            .collect(Collectors.toList());
                    for (Tag tag : tags) {
                        if (!baseMapper.addByArticleTagTable(articleId, tag.getId())) {
                            throw new SystemException(HttpStatusEnum.UPDATE_DATA_ERROR);
                        }
                    }
                }
            } else if (!SystemConstance.ARTICLE_STATUS_DRAFT.equals(status)) {
                throw new SystemException(HttpStatusEnum.PARAM_ERROR);
            }

            if (!updateById(article)) {
                throw new SystemException(HttpStatusEnum.UPDATE_DATA_ERROR);
            }
        } else {

            List<Tag> tagList = null;
            if (!SystemConstance.ARTICLE_STATUS_DRAFT.equals(status)) {
                List<String> tagNameList = articleEditVo.getTagNameList();
                if (!StringUtils.hasText(categoryName)
                        || Objects.isNull(tagNameList)
                        || tagNameList.size() <= 0) {
                    return new ResponseResult(HttpStatusEnum.PARAM_ERROR);
                }
                Category category = categoryService.getCategoryByName(categoryName);
                if (Objects.isNull(category)) {
                    category = new Category().setCategoryName(categoryName);
                    categoryService.addCategories(category);
                }
                article.setCategoryId(category.getId());
                tagList = tagNameList.stream()
                        .map(tagName -> {
                            Tag tag = tagService.getTagByName(tagName);
                            if (Objects.isNull(tag)) {
                                tag = new Tag().setTagName(tagName);
                                tagService.addTags(tag);
                            }
                            return tag;
                        })
                        .collect(Collectors.toList());
            }

            if (!save(article)) {
                throw new SystemException(HttpStatusEnum.INSERT_DATA_ERROR);
            }

            if (Objects.nonNull(tagList)) {
                for (Tag tag : tagList) {
                    if (!baseMapper.addByArticleTagTable(article.getId(), tag.getId())) {
                        throw new SystemException(HttpStatusEnum.INSERT_DATA_ERROR);
                    }
                }
            }


            redisCache.setCacheHashMap(SystemConstance.REDIS_ARTICLE_VIEW_COUNT_KEY, article.getId().toString(), 0);


        }
        return ResponseResult.ok();

    }


    @Override
    public ResponseResult editArticle(Integer articleId) {

        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Article::getId, articleId)
                .eq(Article::getIsDelete, SystemConstance.NOT_DELETE);
        Article article = getOne(queryWrapper);
        if (Objects.isNull(article)) {
            return new ResponseResult(HttpStatusEnum.PARAM_ERROR);
        }

        if (Objects.nonNull(article.getCategoryId())) {
            Category category = categoryService.getById(article.getCategoryId());
            article.setCategoryName(category.getCategoryName());
        }

        ArticleEditVo articleEditVo = BeanCopyUtils.copyObjectByType(article, ArticleEditVo.class);
        List<Tag> tagList = tagService.getTagListByArticle(articleId);
        if (Objects.nonNull(tagList) && tagList.size() > 0) {
            List<String> tagNameList = tagList.stream()
                    .map(tag -> tag.getTagName())
                    .collect(Collectors.toList());
            articleEditVo.setTagNameList(tagNameList);
        }

        return ResponseResult.ok().setData(articleEditVo);
    }

    @Transactional
    @Override
    public ResponseResult deleteArticleByLogic(ReceptionParam receptionParam) {
        Integer isDelete = receptionParam.getIsDelete();
        List<Integer> idList = receptionParam.getIdList();
        if (Objects.isNull(idList)
                || (!isDelete.equals(SystemConstance.IS_DELETE) && !isDelete.equals(SystemConstance.NOT_DELETE))) {
            throw new SystemException(HttpStatusEnum.PARAM_ERROR);
        }
        LambdaUpdateWrapper<Article> updateWrapper = new LambdaUpdateWrapper<>();
        for (Integer id : receptionParam.getIdList()) {
            updateWrapper.clear();
            updateWrapper.eq(Article::getId, id)
                    .set(Article::getIsDelete, isDelete);
            if (!update(updateWrapper)) {
                throw new SystemException(HttpStatusEnum.UPDATE_DATA_ERROR);
            }

        }

        return ResponseResult.ok();
    }

    @Transactional
    @Override
    public ResponseResult deleteArticle(Integer[] articleIdList) {

        for (Integer id : articleIdList) {
            Article article = getById(id);
            if (article.getIsDelete().equals(SystemConstance.NOT_DELETE)) {
                throw new SystemException(HttpStatusEnum.DATA_EXCEPTIONS);
            }

            List<Comment> commentList
                    = commentService.getArticleAllCommentListByIdAndType(id, SystemConstance.LIKE_COUNT_TYPE_BY_ARTICLE);
            commentList.stream()
                    .peek(comment -> {
                        likeCountService.delLikeCountByTargetIdAndType(comment.getId(), SystemConstance.LIKE_COUNT_TYPE_BY_COMMENT);
                    }).collect(Collectors.toList());
            likeCountService.delLikeCountByTargetIdAndType(id, SystemConstance.LIKE_COUNT_TYPE_BY_ARTICLE);

            commentService.deleteCommentByArticleIdAndType(id, SystemConstance.COMMENT_TYPE_BY_ARTICLE_CODE);
            baseMapper.deleteByArticleTagTable(id);


            if (!removeById(id)) {
                throw new SystemException(HttpStatusEnum.REMOVE_DATA_ERROR);
            }

        }
        for (Integer id : articleIdList) {
            redisCache.delCacheHashMaps(SystemConstance.REDIS_ARTICLE_VIEW_COUNT_KEY, id.toString());
        }

        return ResponseResult.ok();

    }

    @Override
    public ResponseResult top(Article article) {
        Integer isTop = article.getIsTop();
        if ((!isTop.equals(SystemConstance.IS_TOP) && !isTop.equals(SystemConstance.NOT_TOP))) {
            throw new SystemException(HttpStatusEnum.PARAM_ERROR);
        }
        LambdaUpdateWrapper<Article> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Article::getId, article.getId())
                .set(Article::getIsTop, isTop)
                .set(Article::getUpdateTime, new Date());
        if (!update(updateWrapper)) {
            return new ResponseResult(HttpStatusEnum.UPDATE_DATA_ERROR);
        }
        return ResponseResult.ok();
    }


    /**
     * 获取全部文章   /  获取公开文章  / 获取私密文章   /获取草稿文章
     *
     * @param current  当前页码
     * @param size     每页显示个数
     * @param keywords 搜索内容
     * @param isDelete 是否已删除
     * @param status   是否是草稿
     * @return
     */
    @Override
    public ResponseResult articles(Integer current,
                                   Integer size,
                                   @Nullable String keywords,
                                   @Nullable Integer isDelete,
                                   @Nullable Integer status,
                                   @Nullable Integer type,
                                   @Nullable Integer categoryId,
                                   @Nullable Integer tagId
    ) {

        Page<Article> page = new Page<>(current, size);
        if (Objects.isNull(tagId)) {
            LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Objects.nonNull(isDelete), Article::getIsDelete, isDelete)
                    .eq(Objects.nonNull(status), Article::getStatus, status)
                    .eq(Objects.nonNull(type), Article::getType, type)
                    .eq(Objects.nonNull(categoryId), Article::getCategoryId, categoryId)
                    .like(StringUtils.hasText(keywords), Article::getArticleTitle, keywords)
                    .orderByDesc(Article::getCreateTime);//从大到小排序
            page(page, queryWrapper);
        } else {
            baseMapper.getArticlesByLogic(page, tagId, keywords, isDelete, status, type, categoryId);
        }
        List<Article> records = page.getRecords();

        records.stream()
                .peek(article -> {
                    Integer articleCategoryId = article.getCategoryId();
                    if (articleCategoryId != null && articleCategoryId > 0) {
                        Category category = categoryService.getById(article.getCategoryId());
                        article.setCategoryName(category.getCategoryName());
                    }
                    List<Tag> tagList = tagService.getTagListByArticle(article.getId());
                    if (Objects.nonNull(tagList) && tagList.size() > 0) {
                        List<TagDTO> tagDTOList = BeanCopyUtils.copyListByType(tagList, TagDTO.class);
                        article.setTagDTOList(tagDTOList);
                    }
                    long likeCount = likeCountService.getLikeCountByTargetIdAndType(article.getId(), SystemConstance.LIKE_COUNT_TYPE_BY_ARTICLE);
                    article.setLikeCount((int) likeCount);
                }).collect(Collectors.toList());

        List<ArticleVo> articleVoList = BeanCopyUtils.copyListByType(records, ArticleVo.class);

        PageVo<ArticleVo> pageVo = new PageVo(page.getTotal(), articleVoList);

        return ResponseResult.ok().setData(pageVo);
    }


    @Override
    public List<Article> getArticleListByGroupByCategoryId() {
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Article::getIsDelete, SystemConstance.NOT_DELETE)
                .ne(Article::getStatus, SystemConstance.ARTICLE_STATUS_DRAFT)
                .groupBy(Article::getCategoryId);

        List<Article> articleList = list(queryWrapper);
        return articleList;
    }

    @Override
    public List<Article> getArticleListByCategory(Integer categoryId, Integer status, Integer isDelete) {

        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Article::getCategoryId, categoryId)
                .ne(Objects.nonNull(status), Article::getStatus, status)
                .eq(Objects.nonNull(isDelete), Article::getIsDelete, isDelete);
        return list(queryWrapper);
    }



    @Override
    public List<Article> getArticleListByCreateTime(Article article) {
        if (Objects.isNull(article.getCreateTime())) {
            throw new SystemException(HttpStatusEnum.PARAM_ERROR);
        }
        String format = DateUtils.format(article.getCreateTime());

        ArticleMapper baseMapper = getBaseMapper();
        List<Article> articleList = baseMapper.getArticleListByCreateTime(format);
        return articleList;
    }


    @Override
    public List<Article> getArticleList() {
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Article::getStatus, SystemConstance.STATUS_PUBLIC)
                .eq(Article::getIsDelete, SystemConstance.NOT_DELETE)
                .orderByDesc(Article::getViewsCount);
        Page<Article> page = new Page<>(SystemConstance.PAGE_CURRENT_MIN, SystemConstance.PAGE_SIZE);
        page(page, queryWrapper);
        return page.getRecords();
    }


    @Override
    public ResponseResult getArticles(Integer current) {
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();

        checkAdmin(queryWrapper);

        queryWrapper.eq(Article::getIsDelete, SystemConstance.NOT_DELETE)
//                .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC)
                .orderByDesc(Article::getIsTop)
                .orderByDesc(Article::getCreateTime);

        Page<Article> page = new Page(current, SystemConstance.PAGE_SIZE);
        page(page, queryWrapper);
        List<Article> articleList = page.getRecords();
        articleList.stream()
                .peek(article -> {
                    List<Tag> tags = tagService.getTagListByArticle(article.getId());
                    List<TagDTO> tagDTOList = BeanCopyUtils.copyListByType(tags, TagDTO.class);
                    article.setTagDTOList(tagDTOList);
                    Category category = categoryService.getById(article.getCategoryId());
                    article.setCategoryName(category.getCategoryName());
                    String content = article.getArticleContent();
                    if (content.length() >= SystemConstance.ARTICLE_LENGTH) {
                        article.setArticleContent(content.substring(0, SystemConstance.ARTICLE_LENGTH));
                    }
                }).collect(Collectors.toList());
        List<ArticleHomeDTO> articleVos = BeanCopyUtils.copyListByType(articleList, ArticleHomeDTO.class);
        return ResponseResult.ok().setData(articleVos);
    }


    @Override
    public ResponseResult getArticleDetail(Integer articleId) {

        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();

        checkAdmin(queryWrapper);

        queryWrapper.eq(Article::getId, articleId)
                .eq(Article::getIsDelete, SystemConstance.NOT_DELETE);
//                .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC);
        Article article = getOne(queryWrapper);

        ArticleDTO articleDTO = BeanCopyUtils.copyObjectByType(article, ArticleDTO.class);

        //获取上下篇文章
        Page<Article> page = new Page<>(SystemConstance.PAGE_CURRENT_MIN, SystemConstance.PAGE_SIZE_MIN);

        queryWrapper.clear();

        checkAdmin(queryWrapper);

        queryWrapper.gt(Article::getCreateTime, article.getCreateTime())
                .eq(Article::getIsDelete, SystemConstance.NOT_DELETE);
//                .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC);
        page(page, queryWrapper);
        if (page.getTotal() > 0) {
            Article nextArticle = page.getRecords().get(0);
            ArticlePreviewDTO nextArticlePreviewDTO = BeanCopyUtils.copyObjectByType(nextArticle, ArticlePreviewDTO.class);
            articleDTO.setNextArticle(nextArticlePreviewDTO);
        }

        queryWrapper.clear();

        checkAdmin(queryWrapper);

        queryWrapper.lt(Article::getCreateTime, article.getCreateTime())
                .eq(Article::getIsDelete, SystemConstance.NOT_DELETE)
//                .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC)
                .orderByDesc(Article::getCreateTime);
        page(page, queryWrapper);
        if (page.getTotal() > 0) {
            Article lastArticle = page.getRecords().get(0);
            ArticlePreviewDTO lastArticlePreviewDTO = BeanCopyUtils.copyObjectByType(lastArticle, ArticlePreviewDTO.class);
            articleDTO.setLastArticle(lastArticlePreviewDTO);
        }

        //获取最新文章
        queryWrapper.clear();

        checkAdmin(queryWrapper);

        queryWrapper.le(Article::getCreateTime, new Date())
                .eq(Article::getIsDelete, SystemConstance.NOT_DELETE)
//                .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC)
                .orderByDesc(Article::getCreateTime);
        page.setSize(SystemConstance.NEW_ARTICLE_SIZE);
        page(page, queryWrapper);
        if (page.getTotal() > 0) {
            List<ArticlePreviewDTO> newArticlePreviewDTOS = BeanCopyUtils.copyListByType(page.getRecords(), ArticlePreviewDTO.class);
            articleDTO.setNewestArticleList(newArticlePreviewDTOS);
        }

        //获取推荐文章
        queryWrapper.clear();

        checkAdmin(queryWrapper);

        queryWrapper.eq(Article::getCategoryId, article.getCategoryId())
                .eq(Article::getIsDelete, SystemConstance.NOT_DELETE)
//                .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC)
                .ne(Article::getId, articleId)
                .ge(Article::getViewsCount, SystemConstance.RECOMMEND_ARTICLE_VIEW_COUNT)
                .orderByDesc(Article::getViewsCount);
        page.setSize(SystemConstance.RECOMMEND_ARTICLE_SIZE);
        page(page, queryWrapper);
        List<Article> recommendArticleList = page.getRecords();
        List<ArticlePreviewDTO> recommendArticlePreviewDTOS;
        if (recommendArticleList.size() < SystemConstance.RECOMMEND_ARTICLE_SIZE) {
            List<LikeCount> likeCountList = likeCountService.getLikeCountByMostLikedArticles(articleId);
            for (LikeCount likeCount : likeCountList) {
                if (likeCount.getCount() > SystemConstance.RECOMMEND_ARTICLE_LIKE_COUNT) {
                    queryWrapper.clear();

                    checkAdmin(queryWrapper);

                    queryWrapper.eq(Article::getId, likeCount.getTargetId())
                            .eq(Article::getCategoryId, article.getCategoryId())
                            .eq(Article::getIsDelete, SystemConstance.NOT_DELETE);
//                            .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC);
                    Article articleById = getOne(queryWrapper);
                    if (Objects.nonNull(articleById)) {
                        recommendArticleList.add(articleById);
                    }
                    if (recommendArticleList.size() == SystemConstance.RECOMMEND_ARTICLE_SIZE) {
                        break;
                    }
                } else {
                    break;
                }
            }

        }
        recommendArticlePreviewDTOS = BeanCopyUtils.copyListByType(recommendArticleList, ArticlePreviewDTO.class);
        List<Tag> tagList = tagService.getTagListByArticle(articleDTO.getId());
        List<TagDTO> tagDTOList = BeanCopyUtils.copyListByType(tagList, TagDTO.class);
        Category category = categoryService.getById(articleDTO.getCategoryId());
        long likeCount = likeCountService.getLikeCountByTargetIdAndType(articleDTO.getId(), SystemConstance.LIKE_COUNT_TYPE_BY_ARTICLE);

        articleDTO.setRecommendArticleList(recommendArticlePreviewDTOS)
                .setCategoryName(category.getCategoryName())
                .setTagDTOList(tagDTOList)
                .setLikeCount((int) likeCount);


        articleViewService.updateArticleViewCount(articleId);

        return ResponseResult.ok().setData(articleDTO);
    }


    @Override
    public ResponseResult searchArticle(Integer current, String keywords) {

        Page<Article> page = new Page<>(current, SystemConstance.PAGE_SIZE);
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();


        checkAdmin(queryWrapper);

        queryWrapper.like(StringUtils.hasText(keywords), Article::getArticleTitle, keywords)
//                .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC)
                .eq(Article::getIsDelete, SystemConstance.NOT_DELETE);
        page(page, queryWrapper);
        if (page.getTotal() <= 0) {
            queryWrapper.clear();

            checkAdmin(queryWrapper);

            queryWrapper.like(StringUtils.hasText(keywords), Article::getArticleContent, keywords)
//                    .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC)
                    .eq(Article::getIsDelete, SystemConstance.NOT_DELETE);

            page(page, queryWrapper);
        }

        List<ArticleSearchDTO> articleSearchDTOS = BeanCopyUtils.copyListByType(page.getRecords(), ArticleSearchDTO.class);
        articleSearchDTOS.stream()
                .peek(dto -> {
                    String articleContent = dto.getArticleContent();
                    if (articleContent.length() > SystemConstance.ARTICLE_LENGTH) {
                        dto.setArticleContent(articleContent.substring(0, SystemConstance.ARTICLE_LENGTH));
                    }
                }).collect(Collectors.toList());

        return ResponseResult.ok().setData(articleSearchDTOS);
    }


    @Override
    public ResponseResult getArticleArchives(Integer current) {
        Page<Article> page = new Page<>(current, SystemConstance.PAGE_SIZE);
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();

        checkAdmin(queryWrapper);

        queryWrapper.eq(Article::getIsDelete, SystemConstance.NOT_DELETE)
//                .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC)
                .orderByDesc(Article::getCreateTime);
        page(page, queryWrapper);
        List<ArticleArchivesVo> previewDTOS = BeanCopyUtils.copyListByType(page.getRecords(), ArticleArchivesVo.class);

        PageVo<ArticleArchivesVo> pageVo = new PageVo(page.getTotal(), previewDTOS);
        return ResponseResult.ok().setData(pageVo);
    }


    @Override
    public ResponseResult getArticlesByCategory(Integer categoryId, Integer tagId, Integer current) {

        ArticlePreviewVo articlePreviewVo;
        if (Objects.nonNull(categoryId)) {
            LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();

            checkAdmin(queryWrapper);

            queryWrapper.eq(Article::getCategoryId, categoryId)
                    .eq(Article::getIsDelete, SystemConstance.NOT_DELETE)
//                    .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC)
                    .orderByDesc(Article::getCreateTime);
            Page<Article> page = new Page<>(current, SystemConstance.PAGE_SIZE);
            page(page, queryWrapper);
            List<ArticleCategoryVo> articleHomeDTOS = BeanCopyUtils.copyListByType(page.getRecords(), ArticleCategoryVo.class);
            Category category = categoryService.getById(categoryId);
            articleHomeDTOS.stream()
                    .peek(dto -> {
                        List<Tag> tagList = tagService.getTagListByArticle(dto.getId());
                        List<TagDTO> tagDTOList = BeanCopyUtils.copyListByType(tagList, TagDTO.class);
                        dto.setCategoryName(category.getCategoryName())
                                .setTagDTOList(tagDTOList);
                    }).collect(Collectors.toList());

            articlePreviewVo = new ArticlePreviewVo();
            articlePreviewVo.setName(category.getCategoryName())
                    .setArticlePreviewList(articleHomeDTOS);
        } else {

            List<Article> articleList;

            try {
                LoginUser loginUser = SecurityUtils.getLoginUser();
                if (SystemConstance.ROLE_ADMIN_ID.equals(loginUser.getRole().getId())){
                    articleList = baseMapper.getArticleListByTagIdNeDraft(tagId);
                }else {
                    articleList = baseMapper.getArticleListByTagIdEqPublic(tagId);
                }
            } catch (Exception exception) {
                articleList = baseMapper.getArticleListByTagIdEqPublic(tagId);
            }

            int size = articleList.size();
            Integer pageSize = SystemConstance.PAGE_SIZE;
            if (size > (current * pageSize)) {
                articleList = articleList.subList((current - 1) * pageSize, current * pageSize);
            } else if (size > ((current - 1) * pageSize)) {
                articleList = articleList.subList((current - 1) * pageSize, size);
            } else {
                articleList = null;
            }
            Tag tag = tagService.getById(tagId);
            articlePreviewVo = new ArticlePreviewVo();
            articlePreviewVo.setName(tag.getTagName());
            if (Objects.nonNull(articleList)) {
                List<ArticleCategoryVo> articleHomeDTOS = BeanCopyUtils.copyListByType(articleList, ArticleCategoryVo.class);
                articlePreviewVo.setArticlePreviewList(articleHomeDTOS);
            }
        }

        return ResponseResult.ok().setData(articlePreviewVo);
    }


    @Override
    public long getArticleCountByCategory(Integer categoryId) {

        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();

        checkAdmin(queryWrapper);

        queryWrapper.eq(Article::getCategoryId, categoryId)
                .eq(Article::getIsDelete, SystemConstance.NOT_DELETE);
//                .eq(Article::getStatus, SystemConstance.STATUS_PUBLIC);

        return count(queryWrapper);
    }


    @Override
    public long getArticleCountByCategoryId(Integer categoryId) {

        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Article::getCategoryId, categoryId)
                .eq(Article::getIsDelete, SystemConstance.NOT_DELETE)
                .ne(Article::getStatus, SystemConstance.ARTICLE_STATUS_DRAFT);

        return count(queryWrapper);
    }


    @Override
    public long getArticleCount(){
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();

        checkAdmin(queryWrapper);

        queryWrapper.eq(Article::getIsDelete,SystemConstance.NOT_DELETE);
        return count(queryWrapper);
    }




    @Override
    public List<Article> getAllArticleList() {
//        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(Article::getIsDelete, SystemConstance.NOT_DELETE)
//                .ne(Article::getStatus, SystemConstance.ARTICLE_STATUS_DRAFT);
//        return list(queryWrapper);
        return list();
    }

    @Override
    public boolean updateArticleViewCount(Integer articleId, @Nullable Integer viewCount) {
        LambdaUpdateWrapper<Article> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Article::getId, articleId)
                .set(Objects.nonNull(viewCount), Article::getViewsCount, viewCount);
        return update(updateWrapper);
    }




    private void checkAdmin(LambdaQueryWrapper<Article> queryWrapper){
        try {
            LoginUser loginUser = SecurityUtils.getLoginUser();
            if (SystemConstance.ROLE_ADMIN_ID.equals(loginUser.getRole().getId())) {
                queryWrapper.ne(Article::getStatus, SystemConstance.ARTICLE_STATUS_DRAFT);
            }else {
                queryWrapper.eq(Article::getStatus, SystemConstance.STATUS_PUBLIC);
            }
        } catch (Exception exception) {
            queryWrapper.eq(Article::getStatus, SystemConstance.STATUS_PUBLIC);
        }
    }

}




